home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / oper_sys / kerberos / pc / krb_libk.lha / Lib / KRB / RECVAUTH.C < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-31  |  9.5 KB  |  289 lines

  1. /*
  2.  * $Source: /afs/athena.mit.edu/astaff/project/kerberos/src/lib/krb/RCS/recvauth.c,v $
  3.  * $Author: jon $
  4.  *
  5.  * Copyright 1987, 1988 by the Massachusetts Institute of Technology.
  6.  *
  7.  * For copying and distribution information, please see the file
  8.  * <mit-copyright.h>.
  9.  */
  10.  
  11. #ifndef    lint
  12. static char rcsid_recvauth_c[] =
  13. "$Header: /afs/athena.mit.edu/astaff/project/kerberos/src/lib/krb/RCS/recvauth.c,v 4.4 90/03/10 19:03:08 jon Exp $";
  14. #endif    lint
  15.  
  16. #include <mit_copy.h>
  17.  
  18. #include <krb.h>
  19. #include <sys\types.h>
  20. #include <netinet\in.h>
  21. /* #include <syslog.h> */
  22. #include <errno.h>
  23. #include <stdio.h>
  24. #include <string.h>
  25.  
  26.  
  27. #define    KRB_SENDAUTH_VERS    "AUTHV0.1" /* MUST be KRB_SENDAUTH_VLEN
  28.                           chars */
  29.  
  30. /*
  31.  * If the protocol changes, you will need to change the version string
  32.  * and make appropriate changes in krb_sendauth.c
  33.  * be sure to support old versions of krb_sendauth!
  34.  */
  35.  
  36.  
  37. /*
  38.  * krb_recvauth() reads (and optionally responds to) a message sent
  39.  * using krb_sendauth().  The "options" argument is a bit-field of
  40.  * selected options (see "sendauth.c" for options description).
  41.  * The only option relevant to krb_recvauth() is KOPT_DO_MUTUAL
  42.  * (mutual authentication requested).  The "fd" argument supplies
  43.  * a file descriptor to read from (and write to, if mutual authenti-
  44.  * cation is requested).
  45.  *
  46.  * Part of the received message will be a Kerberos ticket sent by the
  47.  * client; this is read into the "ticket" argument.  The "service" and
  48.  * "instance" arguments supply the server's Kerberos name.  If the
  49.  * "instance" argument is the string "*", it is treated as a wild card
  50.  * and filled in during the krb_rd_req() call (see read_service_key()).
  51.  *
  52.  * The "faddr" and "laddr" give the sending (client) and receiving
  53.  * (local server) network addresses.  ("laddr" may be left NULL unless
  54.  * mutual authentication is requested, in which case it must be set.)
  55.  *
  56.  * The authentication information extracted from the message is returned
  57.  * in "kdata".  The "filename" argument indicates the file where the
  58.  * server's key can be found.  (It is passed on to krb_rd_req().)  If
  59.  * left null, the default "/etc/srvtab" will be used.
  60.  *
  61.  * If mutual authentication is requested, the session key schedule must
  62.  * be computed in order to reply; this schedule is returned in the
  63.  * "schedule" argument.  A string containing the application version
  64.  * number from the received message is returned in "version", which
  65.  * should be large enough to hold a KRB_SENDAUTH_VLEN-character string.
  66.  *
  67.  * See krb_sendauth() for the format of the received client message.
  68.  *
  69.  * This routine supports another client format, for backward
  70.  * compatibility, consisting of:
  71.  *
  72.  * Size            Variable        Field
  73.  * ----            --------        -----
  74.  *
  75.  * string        tmp_buf, tkt_len    length of ticket, in
  76.  *                         ascii
  77.  *
  78.  * char            ' ' (space char)    separator
  79.  *
  80.  * tkt_len        ticket->dat        the ticket
  81.  *
  82.  * This old-style version does not support mutual authentication.
  83.  *
  84.  * krb_recvauth() first reads the protocol version string from the
  85.  * given file descriptor.  If it doesn't match the current protocol
  86.  * version (KRB_SENDAUTH_VERS), the old-style format is assumed.  In
  87.  * that case, the string of characters up to the first space is read
  88.  * and interpreted as the ticket length, then the ticket is read.
  89.  *
  90.  * If the first string did match KRB_SENDAUTH_VERS, krb_recvauth()
  91.  * next reads the application protocol version string.  Then the
  92.  * ticket length and ticket itself are read.
  93.  *
  94.  * The ticket is decrypted and checked by the call to krb_rd_req().
  95.  * If no mutual authentication is required, the result of the
  96.  * krb_rd_req() call is retured by this routine.  If mutual authenti-
  97.  * cation is required, a message in the following format is returned
  98.  * on "fd":
  99.  *
  100.  * Size            Variable        Field
  101.  * ----            --------        -----
  102.  *
  103.  * 4 bytes        tkt_len            length of ticket or -1
  104.  *                        if error occurred
  105.  *
  106.  * priv_len        tmp_buf            "private" message created
  107.  *                        by krb_mk_priv() which
  108.  *                        contains the incremented
  109.  *                        checksum sent by the client
  110.  *                        encrypted in the session
  111.  *                        key.  (This field is not
  112.  *                        present in case of error.)
  113.  *
  114.  * If all goes well, KSUCCESS is returned; otherwise KFAILURE or some
  115.  * other error code is returned.
  116.  */
  117.  
  118. #ifndef max
  119. #define    max(a,b) (((a) > (b)) ? (a) : (b))
  120. #endif /* max */
  121.  
  122. int
  123. krb_recvauth(options, fd, ticket, service, instance, faddr, laddr, kdata,
  124.          filename, schedule, version)
  125. long options;             /* bit-pattern of options */
  126. int fd;                 /* file descr. to read from */
  127. KTEXT ticket;             /* storage for client's ticket */
  128. char *service;             /* service expected */
  129. char *instance;             /* inst expected (may be filled in) */
  130. struct sockaddr_in *faddr;     /* address of foreign host on fd */
  131. struct sockaddr_in *laddr;     /* local address */
  132. AUTH_DAT *kdata;         /* kerberos data (returned) */
  133. char *filename;             /* name of file with service keys */
  134. Key_schedule schedule;         /* key schedule (return) */
  135. char *version;             /* version string (filled in) */
  136. {
  137.  
  138.     int i, cc, old_vers = 0;
  139.     char krb_vers[KRB_SENDAUTH_VLEN + 1]; /* + 1 for the null terminator */
  140.     char *cp;
  141.     int rem;
  142.     long tkt_len, priv_len;
  143.     u_long cksum;
  144.     u_char tmp_buf[MAX_KTXT_LEN+max(KRB_SENDAUTH_VLEN+1,21)];
  145.  
  146.     /* read the protocol version number */
  147.     if (krb_net_read(fd, krb_vers, KRB_SENDAUTH_VLEN) !=
  148.     KRB_SENDAUTH_VLEN)
  149.         return(errno);
  150.     krb_vers[KRB_SENDAUTH_VLEN] = '\0';
  151.  
  152.     /* check version string */
  153.     if (strcmp(krb_vers,KRB_SENDAUTH_VERS)) {
  154.     /* Assume the old version of sendkerberosdata: send ascii
  155.        length, ' ', and ticket. */
  156.     if (options & KOPT_DO_MUTUAL)
  157.         return(KFAILURE);     /* XXX can't do old style with mutual auth */
  158.     old_vers = 1;
  159.  
  160.     /* copy what we have read into tmp_buf */
  161.     (void) bcopy(krb_vers, (char *) tmp_buf, KRB_SENDAUTH_VLEN);
  162.  
  163.     /* search for space, and make it a null */
  164.     for (i = 0; i < KRB_SENDAUTH_VLEN; i++)
  165.         if (tmp_buf[i]== ' ') {
  166.         tmp_buf[i] = '\0';
  167.         /* point cp to the beginning of the real ticket */
  168.         cp = (char *) &tmp_buf[i+1];
  169.         break;
  170.         }
  171.  
  172.     if (i == KRB_SENDAUTH_VLEN)
  173.         /* didn't find the space, keep reading to find it */
  174.         for (; i<20; i++) {
  175.         if (read(fd, (char *)&tmp_buf[i], 1) != 1) {
  176.             return(KFAILURE);
  177.         }
  178.         if (tmp_buf[i] == ' ') {
  179.             tmp_buf[i] = '\0';
  180.             /* point cp to the beginning of the real ticket */
  181.             cp = (char *) &tmp_buf[i+1];
  182.             break;
  183.         }
  184.         }
  185.  
  186.     tkt_len = (long) atoi((char *) tmp_buf);
  187.  
  188.     /* sanity check the length */
  189.     if ((i==20)||(tkt_len<=0)||(tkt_len>MAX_KTXT_LEN))
  190.         return(KFAILURE);
  191.  
  192.     if (i < KRB_SENDAUTH_VLEN) {
  193.         /* since we already got the space, and part of the ticket,
  194.            we read fewer bytes to get the rest of the ticket */
  195.         if (krb_net_read(fd, (char *)(tmp_buf+KRB_SENDAUTH_VLEN),
  196.                  (int) (tkt_len - KRB_SENDAUTH_VLEN + 1 + i))
  197.         != (int)(tkt_len - KRB_SENDAUTH_VLEN + 1 + i))
  198.         return(errno);
  199.     } else {
  200.         if (krb_net_read(fd, (char *)(tmp_buf+i), (int)tkt_len) !=
  201.         (int) tkt_len)
  202.         return(errno);
  203.     }
  204.     ticket->length = tkt_len;
  205.     /* copy the ticket into the struct */
  206.     (void) bcopy(cp, (char *) ticket->dat, ticket->length);
  207.  
  208.     } else {
  209.     /* read the application version string */
  210.     if (krb_net_read(fd, version, KRB_SENDAUTH_VLEN) !=
  211.         KRB_SENDAUTH_VLEN)
  212.         return(errno);
  213.     version[KRB_SENDAUTH_VLEN] = '\0';
  214.  
  215.     /* get the length of the ticket */
  216.     if (krb_net_read(fd, (char *)&tkt_len, sizeof(tkt_len)) !=
  217.         sizeof(tkt_len))
  218.         return(errno);
  219.     
  220.     /* sanity check */
  221.     ticket->length = ntohl((unsigned long)tkt_len);
  222.     if ((ticket->length <= 0) || (ticket->length > MAX_KTXT_LEN)) {
  223.         if (options & KOPT_DO_MUTUAL) {
  224.         rem = KFAILURE;
  225.         goto mutual_fail;
  226.         } else
  227.         return(KFAILURE); /* XXX there may still be junk on the fd? */
  228.     }
  229.  
  230.     /* read the ticket */
  231.     if (krb_net_read(fd, (char *) ticket->dat, ticket->length)
  232.         != ticket->length)
  233.         return(errno);
  234.     }
  235.     /*
  236.      * now have the ticket.  decrypt it to get the authenticated
  237.      * data.
  238.      */
  239.     rem = krb_rd_req(ticket,service,instance,faddr->sin_addr.s_addr,
  240.              kdata,filename);
  241.  
  242.     if (old_vers) return(rem);     /* XXX can't do mutual with old client */
  243.  
  244.     /* if we are doing mutual auth, compose a response */
  245.     if (options & KOPT_DO_MUTUAL) {
  246.     if (rem != KSUCCESS)
  247.         /* the krb_rd_req failed */
  248.         goto mutual_fail;
  249.  
  250.     /* add one to the (formerly) sealed checksum, and re-seal it
  251.        for return to the client */
  252.     cksum = kdata->checksum + 1;
  253.     cksum = htonl(cksum);
  254. #ifndef NOENCRYPTION
  255.     key_sched(kdata->session,schedule);
  256. #endif /* !NOENCRYPTION */
  257.     priv_len = krb_mk_priv((unsigned char *)&cksum,
  258.                    tmp_buf,
  259.                    (unsigned long) sizeof(cksum),
  260.                    schedule,
  261.                    kdata->session,
  262.                    laddr,
  263.                    faddr);
  264.     if (priv_len < 0) {
  265.         /* re-sealing failed; notify the client */
  266.         rem = KFAILURE;     /* XXX */
  267. mutual_fail:
  268.         priv_len = -1;
  269.         tkt_len = htonl((unsigned long) priv_len);
  270.         /* a length of -1 is interpreted as an authentication
  271.            failure by the client */
  272.         if ((cc = krb_net_write(fd, (char *)&tkt_len, sizeof(tkt_len)))
  273.         != sizeof(tkt_len))
  274.         return(cc);
  275.         return(rem);
  276.     } else {
  277.         /* re-sealing succeeded, send the private message */
  278.         tkt_len = htonl((unsigned long)priv_len);
  279.         if ((cc = krb_net_write(fd, (char *)&tkt_len, sizeof(tkt_len)))
  280.          != sizeof(tkt_len))
  281.         return(cc);
  282.         if ((cc = krb_net_write(fd, (char *)tmp_buf, (int) priv_len))
  283.         != (int) priv_len)
  284.         return(cc);
  285.     }
  286.     }
  287.     return(rem);
  288. }
  289.